package helper;

import javax.servlet.http.HttpSession;

import org.mybeans.dao.DAOException;

import databeans.Answer;
import databeans.Binaryq;
import databeans.Entity;
import databeans.EntityAttribute;
import databeans.EntityClass;
import databeans.Likertq;
import databeans.MultipleChoiceq;
import databeans.Question;
import databeans.SocioCognitiveq;
import databeans.Survey;

import model.AnswerDAO;
import model.BinaryqDAO;
import model.EntityAttributeDAO;
import model.EntityClassDAO;
import model.EntityDAO;
import model.LikertqDAO;
import model.MultipleChoiceqDAO;
import model.QuestionDAO;
import model.SocioCognitiveqDAO;

public class GenerateDynetml {
	
	private static HttpSession session;
	private static AnswerDAO answerDAO;
	private static QuestionDAO questionDAO;
	private static EntityClassDAO ecDAO;
	private static EntityDAO entityDAO;
	private static EntityAttributeDAO eaDAO;
	private static BinaryqDAO binaryqDAO;
	private static LikertqDAO likertqDAO;
	private static MultipleChoiceqDAO mcDAO;
	private static SocioCognitiveqDAO scDAO;
	private static StringBuffer output = null;
	
	private static Survey survey;

    public static StringBuffer generate(HttpSession sess, AnswerDAO aDAO, QuestionDAO qDAO, EntityClassDAO encDAO, EntityDAO eDAO, EntityAttributeDAO enaDAO,
    		BinaryqDAO binDAO, LikertqDAO likDAO, MultipleChoiceqDAO mcqDAO, SocioCognitiveqDAO scqDAO) {
    	try {
    		session = sess;
    		answerDAO = aDAO;
    		questionDAO = qDAO;
    		ecDAO = encDAO;
    		entityDAO = eDAO;
    		eaDAO = enaDAO;
    		binaryqDAO = binDAO;
    		likertqDAO = likDAO;
    		mcDAO = mcqDAO;
    		scDAO = scqDAO;
    		
    		survey = (Survey) session.getAttribute("survey");
    		
	    	output = new StringBuffer();
	    	writeLine(output, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>");
	    	writeLine(output, "  <DynamicMetaNetwork>");
	    	writeLine(output, "    <MetaNetwork>");
	    	writeLine(output, "      <nodes>");
	    	
	    	writeNodeClasses();
	    	
	    	writeLine(output, "      </nodes>");
	    	writeLine(output, "      <networks>");
	    	
	    	writeNetworkClasses();
	    	
	    	writeLine(output, "      </networks>");
	    	writeLine(output, "    </MetaNetwork>");
	    	writeLine(output, "  </DynamicMetaNetwork>");
	    	
	    	System.out.println("hi");
	    	
	    	return output;
    	} catch (DAOException e) {
    		e.printStackTrace();
    	}
		return null;
    }
    
    private static void writeNodeClasses() throws DAOException {
    	EntityClass[] eclist = ecDAO.getEntityClassBySid(survey.getSid());
    	for (int i = 0; i < eclist.length; i++)
    		writeNodes(eclist[i]);
    }
    
    private static void writeNodes(EntityClass ec) throws DAOException {
    	Entity[] elist = entityDAO.getEntityByEcid(ec.getEcid());
    	
    	writeLine(output, "        <nodeclass type=\"" + convertEntityType(ec.getType()) + "\" id=\"" + ec.getName() + "\">");
    	writeLine(output, "          <propertyIdentities>");
    	
    	if (ec.getName().equals("Respondents")) { // Special case for respondents
    		Question[] questionlist = questionDAO.getNonNetworkQuestionBySid(survey.getSid());
    		for (int i = 0; i < questionlist.length; i++) {
    			writeLine(output, "            <propertyIdentity id=\"" + questionlist[i].getDynetmlAttr() + 
    					"\" type=\"" + convertEntityAttrType(questionlist[i].getDynetmlType()) + 
    					"\" singleValued=\"" + "false" + "\"/>");
    		}
    		writeLine(output, "          </propertyIdentities>");
    		
    		for (int i = 0; i < elist.length; i++) {
				writeLine(output, "          <node id=\"" + elist[i].getId() + "\" title=\"" + elist[i].getName() + "\">");
    			for (int j = 0; j < questionlist.length; j++) {
    				Answer answer = answerDAO.getAnswerByQidUsernameNN(questionlist[j].getQid(), elist[i].getName());
    				if (answer == null)
    					continue;
    				writeLine(output, "            <property id=\"" + questionlist[j].getDynetmlAttr() + 
    						"\" value=\"" + convertAnswer(answer.getAnswer(), questionlist[j].getType(), questionlist[j].getQid()) + "\"/>");
    			}
    			writeLine(output, "          </node>");
    		}
    	}
    	else {
    		String[] attrlist = eaDAO.getAllAttributesByEcid(ec.getEcid());
    		for (int i = 0; i < attrlist.length; i++) {
    			writeLine(output, "            <propertyIdentity id=\"" + attrlist[i] + "\" type=\"" + "text" + "\" singleValued=\"" + "false" + "\"/>");
    		}
    		writeLine(output, "          </propertyIdentities>");
    		
    		for (int i = 0; i < elist.length; i++) {
        		writeLine(output, "          <node id=\"" + elist[i].getId() + "\" title=\"" + elist[i].getName() + "\">");
        		EntityAttribute[] ealist = eaDAO.getAttrByEid(elist[i].getEid());
        		for (int j = 0; j < ealist.length; j++) {
        			writeLine(output, "            <property id=\"" + ealist[j].getAttrname() + "\" value=\"" + ealist[j].getValue() + "\"/>");
        		}
        		writeLine(output, "          </node>");
    		}
    	}
    	writeLine(output, "        </nodeclass>");
    }
    
    private static void writeNetworkClasses() throws DAOException {
    	Question[] questionlist = questionDAO.getNetworkQuestionBySid(survey.getSid());
    	for (int i = 0; i < questionlist.length; i++)
    		writeNetworks(questionlist[i]);
    }
    
    private static void writeNetworks(Question question) throws DAOException {
    	EntityClass ecFrom = ecDAO.lookupBySidName(survey.getSid(), question.getEntityFrom());
    	EntityClass ecTo = ecDAO.lookupBySidName(survey.getSid(), question.getEntityTo());
    	EntityClass ecResp = ecDAO.lookupBySidName(survey.getSid(), "Respondents");
    	
    	String fromType = convertEntityType(ecFrom.getType());
    	String toType = convertEntityType(ecTo.getType());

    	writeLine(output, "        <network id=\"" + fromType + " x " + toType + " " + question.getDynetmlAttr() + 
    			"\" source=\"" + ecFrom.getName() + "\" sourceType=\"" + fromType + 
    			"\" target=\"" + ecTo.getName() + "\" targetType=\"" + toType + "\">");
    	
    	Entity[] entityResp = entityDAO.getEntityByEcid(ecResp.getEcid());
    	if (question.getType() != QuestionType.NETWORK_SOCIO_COGNITIVE) {
	    	for (int i = 0; i < entityResp.length; i++) {
	    		Answer[] answerlist = answerDAO.getAnswerByQidUsername(question.getQid(), entityResp[i].getName());
	    		if (answerlist == null || answerlist.length == 0)
	    			continue;
	    		
	    		for (int j = 0; j < answerlist.length; j++) {
	    			if (answerlist[j].getEntityname().equals("")) // Special case for network binary where nothing is checked
	    				continue;
	    			Entity sourceEntity = entityDAO.getEntityByEcidName(ecFrom.getEcid(), answerlist[j].getUsername()); //??????
	        		Entity targetEntity = entityDAO.getEntityByEcidName(ecTo.getEcid(), answerlist[j].getEntityname());
	    	    	writeLine(output, "          <link source=\"" + sourceEntity.getId() + 
	    	    			"\" target=\"" + targetEntity.getId() + "\" value=\"" + answerlist[j].getAnswer() + "\"/>");
	    		}
	    	}
    	}
    	else {
    		Entity[] entityTo = entityDAO.getEntityByEcid(ecTo.getEcid());
    		Entity[] entityFrom = entityDAO.getEntityByEcid(ecFrom.getEcid());
    		int[][] scAnswer = new int[entityFrom.length][entityTo.length];
    		for (int i = 0; i < entityFrom.length; i++) {
    			for (int j = 0; j < entityTo.length; j++) {
    				scAnswer[i][j] = 0;
    			}
    		}
    		
    		SocioCognitiveq scq = scDAO.lookup(question.getQid());
    		if (scq.getType() == SocioCognitiveType.UNION) {
    			for (int i = 0; i < entityResp.length; i++) {
    				for (int j = 0; j < entityFrom.length; j++) {
    					for (int k = 0; k < entityTo.length; k++) {
        					Answer answer = answerDAO.lookup(question.getQid(), entityResp[i].getName(), entityFrom[j].getName(), entityTo[k].getName());
    						if (answer != null) {
    							scAnswer[j][k] = 1;
    						}
    					}
    				}
    			}
    		}
    		else if (scq.getType() == SocioCognitiveType.AVERAGE) {
    			for (int i = 0; i < entityResp.length; i++) {
    				for (int j = 0; j < entityFrom.length; j++) {
    					for (int k = 0; k < entityTo.length; k++) {
        					Answer answer = answerDAO.lookup(question.getQid(), entityResp[i].getName(), entityFrom[j].getName(), entityTo[k].getName());
    						if (answer != null) {
    							scAnswer[j][k] += 1;
    						}
    					}
    				}
    			}
    		}
    		else if (scq.getType() == SocioCognitiveType.CONFIRMED) {
    			
    		}
    		else {
    			
    		}
    		
    		for (int i = 0; i < entityFrom.length; i++) {
    			for (int j = 0; j < entityTo.length; j++) {
    				int answer = scAnswer[i][j];
    				if (answer != 0) {
    		    		writeLine(output, "          <link source=\"" + entityFrom[i].getId() + 
    			    			"\" target=\"" + entityTo[j].getId() + "\" value=\"" + answer + "\"/>");
    				}
    			}
    		}
    	}
    	writeLine(output, "        </network>");
    }
    
    private static void writeLine(StringBuffer sb, String str) {
    	sb.append(str);
    	sb.append(System.getProperty("line.separator"));
    }
    
    private static String convertEntityType(int type) {
    	if (type == EntityType.AGENT)
    		return "Agent";
    	else if (type == EntityType.ORGANIZATION)
    		return "Organization";
    	else if (type == EntityType.KNOWLEDGE)
    		return "Knowledge";
    	else if (type == EntityType.RESOURCE)
    		return "Resource";
    	else if (type == EntityType.BELIEF)
    		return "Belief";
    	else if (type == EntityType.EVENT)
    		return "Event";
    	else if (type == EntityType.TASK)
    		return "Task";
    	else if (type == EntityType.LOCATION)
    		return "Location";
    	else if (type == EntityType.ROLE)
    		return "Role";
    	else if (type == EntityType.ACTION)
    		return "Action";
    	else
    		return "Unknown";
    }
    
    private static String convertEntityAttrType(int type) {
    	if (type == EntityAttributeType.TEXT)
    		return "text";
    	else if (type == EntityAttributeType.CATEGORY_TEXT)
    		return "categoryText";
    	else if (type == EntityAttributeType.NUMBER)
    		return "number";
    	else if (type == EntityAttributeType.CATEGORY_NUMBER)
    		return "categoryNumber";
    	else if (type == EntityAttributeType.DATE)
    		return "date";
    	else if (type == EntityAttributeType.URI)
    		return "uri";
    	else
    		return "unknown";
    }
    
    private static String convertAnswer(String answer, int qtype, int qid) throws DAOException {
    	if (qtype == QuestionType.BINARY) {
    		Binaryq binary = binaryqDAO.lookup(qid);
    		if (answer.equals("0"))
    			return binary.getNo();
    		else
    			return binary.getYes();
    	}
    	else if (qtype == QuestionType.NUMERIC)
    		return answer;
    	else if (qtype == QuestionType.OPEN_ENDED)
    		return answer;
    	else if (qtype == QuestionType.LIKERT) {
    		Likertq likert = likertqDAO.lookup(qid);
    		if (answer.equals("1"))
    			return likert.getChoice1();
    		else if (answer.equals("2"))
    			return likert.getChoice2();
    		else if (answer.equals("3"))
    			return likert.getChoice3();
    		else if (answer.equals("4"))
    			return likert.getChoice4();
    		else if (answer.equals("5"))
    			return likert.getChoice5();
    		else if (answer.equals("6"))
    			return likert.getChoice6();
    		else
    			return likert.getChoice7();
    	}
    	else if (qtype == QuestionType.MULTIPLE_CHOICE) {
    		MultipleChoiceq mcq = mcDAO.lookup(qid, Integer.parseInt(answer));
    		return mcq.getChoiceDesc();
    	}
    	else if (qtype == QuestionType.MULTIPLE_SELECTION)
    		return answer;
    	else if (qtype == QuestionType.RANK_ORDER)
    		return answer;
    	else if (qtype == QuestionType.CONTINUOUS)
    		return answer;
    	else
    		return answer;
    }
  } 
